Pact をやめた理由
そもそも microservice 化していく段階でサービス間通信のテストが難しくなることはわかっていたので、なんとか手を打ちたかったので使い始めたのが Pact だった。 で、導入の経緯は下記にあるように JSON over HTTP を使いつつ、サービス間連携を Consumer-Driven Contract testing でなんとかしようと思った。
クックパッドでは各サービス間の連携には、Protocol Buffers や Thrift を用いた RPC を利用するのではなく、JSON over HTTP を利用する方針にしています。この理由としては、現状そこまでパフォーマンスがボトルネックになっていないことがあり、また、デバッギングの容易性や Rails の RESTful な思想との親和性や既存のミドルウェアの再利用といった開発効率のほうを優先しているからです。
で、そのための運用ノウハウもいろいろ溜まってきた。
というように結構本気で運用してた。なんかちょっと手を出してみるかとかそういうレベルじゃなく、コントリビュートしながらやるくらいには本気でやってた。
先に補足しておくとこれは俺が見誤ってたというだけで会社全体でとかそういうのではないです。
で、じゃぁ何が問題になってきたかというとまずはそもそも俺は問題を見誤っていたというのがある。
サービス間通信の問題になるのを個々のサービス同士の通信で起きる問題だと思ってたんだよね。
https://gyazo.com/da974378aeb657de00a8de8eedc50b9e
この A と B での通信が主な問題だと思ってた。Pact とかは主にここをテストするもの。 でも本当に複雑で難しいのはそこじゃなくて全体の通信だったんだよね。https://gyazo.com/1a88815669d392c1f62b69a06ef06e55
例えば上の図でいうと……
1. A が通信している backend の一つがレスポンスが少し遅くなる
2. それに引きづられて A が B に返すレスポンスが遅くなる
3. B が C に返すレスポンスがさらに遅くなる
4. 端末へのレスポンスがタイムアウトになってしまう
みたいなのが発生する。
状況としては C のレスポンスが遅いせいなんだけど、たどっていくと A のバックエンドが少し遅くなったのが原因だったりする。
個々で見てると少ししか遅くなってないのでエラーとして拾えないけどいろいろたどった結果エラーになるとかが発生する。
ということでサービス間通信に問題が発生しそう!!っていう気づきは良かったんだけどちょっと問題の範囲を見誤ってたんだよね。
で、じゃぁそもそも最初に Pact で見ていた個々のサービス間の通信はどうやって担保するのかっていうと、実は Pact みたいにガッツリやるくらいなら RPC でもあまり変わらないんじゃない?というのもあって gRPC に移行してたりする。 あとはエラーが絶対に発生しないようにガッツリコスト書けてテストを書いたりするより、カナリアリリースとか Chaos Engineering とかでエラーが発生してもすぐに気付ける環境を用意する方向がよいのかなと思ってる。